home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gas / gassrc04.zoo / app.c < prev    next >
C/C++ Source or Header  |  1993-03-02  |  8KB  |  399 lines

  1. /* This is the Assembler Pre-Processor
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* App, the assembler pre-processor.  This pre-processor strips out excess
  21.    spaces, turns single-quoted characters into a decimal constant, and turns
  22.    # <number> <filename> <garbage> into a .line <number>;.file <filename> pair.
  23.    This needs better error-handling.
  24.  */
  25. #include <stdio.h>
  26. #ifdef USG
  27. #define bzero(s,n) memset(s,0,n)
  28. #endif
  29. #if !defined(__STDC__) && !defined(const)
  30. #define const /* Nothing */
  31. #endif
  32.  
  33. static char    lex [256];
  34. static const char    symbol_chars[] = 
  35.     "$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  36.  
  37. extern const char comment_chars[];
  38. extern const char line_comment_chars[];
  39.  
  40. #define LEX_IS_SYMBOL_COMPONENT        (1)
  41. #define LEX_IS_WHITESPACE        (2)
  42. #define LEX_IS_LINE_SEPERATOR        (4)
  43. #define LEX_IS_COMMENT_START        (8)    /* JF added these two */
  44. #define LEX_IS_LINE_COMMENT_START    (16)
  45. #define IS_SYMBOL_COMPONENT(c)        (lex [c] & LEX_IS_SYMBOL_COMPONENT)
  46. #define IS_WHITESPACE(c)        (lex [c] & LEX_IS_WHITESPACE)
  47. #define IS_LINE_SEPERATOR(c)        (lex [c] & LEX_IS_LINE_SEPERATOR)
  48. #define IS_COMMENT(c)            (lex [c] & LEX_IS_COMMENT_START)
  49. #define IS_LINE_COMMENT(c)        (lex [c] & LEX_IS_LINE_COMMENT_START)
  50.  
  51. void
  52. do_scrub_begin()
  53. {
  54.     const char *p;
  55.  
  56.     bzero (lex, sizeof(lex));        /* Trust NOBODY! */
  57.     lex [' ']        |= LEX_IS_WHITESPACE;
  58.     lex ['\t']        |= LEX_IS_WHITESPACE;
  59.     for (p =symbol_chars;*p;++p)
  60.         lex [*p] |= LEX_IS_SYMBOL_COMPONENT;
  61.     lex ['\n']        |= LEX_IS_LINE_SEPERATOR;
  62. #ifdef DONTDEF
  63.     lex [':']        |= LEX_IS_LINE_SEPERATOR;
  64. #endif
  65.     lex [';']        |= LEX_IS_LINE_SEPERATOR;
  66.     for (p=comment_chars;*p;p++)
  67.         lex[*p] |= LEX_IS_COMMENT_START;
  68.     for (p=line_comment_chars;*p;p++)
  69.         lex[*p] |= LEX_IS_LINE_COMMENT_START;
  70. }
  71.  
  72. FILE *scrub_file;
  73.  
  74. int
  75. scrub_from_file()
  76. {
  77. #ifdef atarist
  78.     int c;
  79.     if((c = getc(scrub_file)) == '\r') c = getc(scrub_file);
  80.     return c;
  81. #else
  82.     return getc(scrub_file);
  83. #endif
  84. }
  85.  
  86. void
  87. scrub_to_file(ch)
  88. int ch;
  89. {
  90.     ungetc(ch,scrub_file);
  91. }
  92.  
  93. char *scrub_string;
  94. char *scrub_last_string;
  95.  
  96. int
  97. scrub_from_string()
  98. {
  99.     return scrub_string == scrub_last_string ? EOF : *scrub_string++;
  100. }
  101.  
  102. void
  103. scrub_to_string(ch)
  104. int ch;
  105. {
  106.     *--scrub_string=ch;
  107. }
  108.  
  109. int
  110. do_scrub_next_char(get,unget)
  111. int (*get)();
  112. void (*unget)();
  113. /* FILE *fp; */
  114. {
  115.     /* State 0: beginning of normal line
  116.         1: After first whitespace on normal line (flush more white)
  117.         2: After first non-white on normal line (keep 1white)
  118.         3: after second white on normal line (flush white)
  119.         4: after putting out a .line, put out digits
  120.         5: parsing a string, then go to old-state
  121.         6: putting out \ escape in a "d string.
  122.         7: After putting out a .file, put out string.
  123.         8: After putting out a .file string, flush until newline.
  124.         -1: output string in out_string and go to the state in old_state
  125.         -2: flush text until a '*' '/' is seen, then go to state old_state
  126.     */
  127.  
  128.     static state;
  129.     static old_state;
  130.     static char *out_string;
  131.     static char out_buf[20];
  132.     static add_newlines;
  133.     int ch;
  134.  
  135.     if(state==-1) {
  136.         ch= *out_string++;
  137.         if(*out_string==0) {
  138.             state=old_state;
  139.             old_state=3;
  140.         }
  141.         return ch;
  142.     }
  143.     if(state==-2) {
  144.         for(;;) {
  145.             do ch=(*get)();
  146.             while(ch!=EOF && ch!='\n' && ch!='*');
  147.             if(ch=='\n' || ch==EOF)
  148.                 return ch;
  149.              ch=(*get)();
  150.              if(ch==EOF || ch=='/')
  151.                  break;
  152.             (*unget)(ch);
  153.         }
  154.         state=old_state;
  155.         return ' ';
  156.     }
  157.     if(state==4) {
  158.         ch=(*get)();
  159.         if(ch==EOF || (ch>='0' && ch<='9'))
  160.             return ch;
  161.         else {
  162.             while(ch!=EOF && IS_WHITESPACE(ch))
  163.                 ch=(*get)();
  164.             if(ch=='"') {
  165.                 (*unget)(ch);
  166.                 out_string="; .file ";
  167.                 old_state=7;
  168.                 state= -1;
  169.                 return *out_string++;
  170.             } else {
  171.                 while(ch!=EOF && ch!='\n')
  172.                     ch=(*get)();
  173.                 return ch;
  174.             }
  175.         }
  176.     }
  177.     if(state==5) {
  178.         ch=(*get)();
  179.         if(ch=='"') {
  180.             state=old_state;
  181.             return '"';
  182.         } else if(ch=='\\') {
  183.             state=6;
  184.             return ch;
  185.         } else if(ch==EOF) {
  186.             as_warn("End of file in string: inserted '\"'");
  187.              state=old_state;
  188.             (*unget)('\n');
  189.             return '"';
  190.         } else {
  191.             return ch;
  192.         }
  193.     }
  194.     if(state==6) {
  195.         state=5;
  196.         ch=(*get)();
  197.         switch(ch) {
  198.             /* This is neet.  Turn "string
  199.                more string" into "string\n  more string"
  200.              */
  201.         case '\n':
  202.             (*unget)('n');
  203.             add_newlines++;
  204.             return '\\';
  205.  
  206.         case '"':
  207.         case '\\':
  208.         case 'b':
  209.         case 'f':
  210.         case 'n':
  211.         case 'r':
  212.         case 't':
  213.         case '0':
  214.         case '1':
  215.         case '2':
  216.         case '3':
  217.         case '4':
  218.         case '5':
  219.         case '6':
  220.         case '7':
  221.             break;
  222.         default:
  223.             as_warn("Unknown escape '\\%c' in string: Ignored",ch);
  224.             break;
  225.  
  226.         case EOF:
  227.             as_warn("End of file in string: '\"' inserted");
  228.             return '"';
  229.         }
  230.         return ch;
  231.     }
  232.  
  233.     if(state==7) {
  234.         ch=(*get)();
  235.         state=5;
  236.         old_state=8;
  237.         return ch;
  238.     }
  239.  
  240.     if(state==8) {
  241.         do ch= (*get)();
  242.         while(ch!='\n');
  243.         state=0;
  244.         return ch;
  245.     }
  246.  
  247.  flushchar:
  248.     ch=(*get)();
  249.     switch(ch) {
  250.     case ' ':
  251.     case '\t':
  252.         do ch=(*get)();
  253.         while(ch!=EOF && IS_WHITESPACE(ch));
  254.         if(ch==EOF)
  255.             return ch;
  256.         if(IS_COMMENT(ch) || (state==0 && IS_LINE_COMMENT(ch)) || ch=='/' || IS_LINE_SEPERATOR(ch)) {
  257.             (*unget)(ch);
  258.             goto flushchar;
  259.         }
  260.         (*unget)(ch);
  261.         if(state==0 || state==2) {
  262.             state++;
  263.             return ' ';
  264.         } else goto flushchar;
  265.  
  266.     case '/':
  267.         ch=(*get)();
  268.         if(ch=='*') {
  269.             for(;;) {
  270.                 do {
  271.                     ch=(*get)();
  272.                     if(ch=='\n')
  273.                         add_newlines++;
  274.                 } while(ch!=EOF && ch!='*');
  275.                 ch=(*get)();
  276.                 if(ch==EOF || ch=='/')
  277.                     break;
  278.                 (*unget)(ch);
  279.             }
  280.             if(ch==EOF)
  281.                 as_warn("End of file in '/' '*' string: */ inserted");
  282.  
  283.             (*unget)(' ');
  284.             goto flushchar;
  285.         } else {
  286.             if(IS_COMMENT('/') || (state==0 && IS_LINE_COMMENT('/'))) {
  287.                 (*unget)(ch);
  288.                 ch='/';
  289.                 goto deal_misc;
  290.             }
  291.             if(ch!=EOF)
  292.                 (*unget)(ch);
  293.             return '/';
  294.         }
  295.         break;
  296.  
  297.     case '"':
  298.         old_state=state;
  299.         state=5;
  300.         return '"';
  301.         break;
  302.  
  303.     case '\'':
  304.         ch=(*get)();
  305.         if(ch==EOF) {
  306.             as_warn("End-of-file after a ': \000 inserted");
  307.             ch=0;
  308.         }
  309.         sprintf(out_buf,"(%d)",ch&0xff);
  310.         old_state=state;
  311.         state= -1;
  312.         out_string=out_buf;
  313.         return *out_string++;
  314.  
  315.     case ':':
  316.         if(state!=3)
  317.             state=0;
  318.         return ch;
  319.  
  320.     case '\n':
  321.         if(add_newlines) {
  322.             --add_newlines;
  323.             (*unget)(ch);
  324.         }
  325.     case ';':
  326.         state=0;
  327.         return ch;
  328.  
  329.     default:
  330.     deal_misc:
  331.         if(state==0 && IS_LINE_COMMENT(ch)) {
  332.             do ch=(*get)();
  333.             while(ch!=EOF && IS_WHITESPACE(ch));
  334.             if(ch==EOF) {
  335.                 as_warn("EOF in comment:  Newline inserted");
  336.                 return '\n';
  337.             }
  338.             if(ch<'0' || ch>'9') {
  339.                 while(ch!=EOF && ch!='\n')
  340.                     ch=(*get)();
  341.                 if(ch==EOF)
  342.                     as_warn("EOF in Comment: Newline inserted");
  343.                 state=0;
  344.                 return '\n';
  345.             }
  346.             (*unget)(ch);
  347.             old_state=4;
  348.             state= -1;
  349.             out_string=".line ";
  350.             return *out_string++;
  351.  
  352.         } else if(IS_COMMENT(ch)) {
  353.             do ch=(*get)();
  354.             while(ch!=EOF && ch!='\n');
  355.             if(ch==EOF)
  356.                 as_warn("EOF in comment:  Newline inserted");
  357.             state=0;
  358.             return '\n';
  359.  
  360.         } else if(state==0) {
  361.             state=2;
  362.             return ch;
  363.         } else if(state==1) {
  364.             state=2;
  365.             return ch;
  366.         } else {
  367.             return ch;
  368.  
  369.         }
  370.     case EOF:
  371.         if(state==0)
  372.             return ch;
  373.         as_warn("End-of-File not at end of a line");
  374.     }
  375.     return -1;
  376. }
  377.  
  378. #ifdef TEST
  379.  
  380. char comment_chars[] = "|";
  381. char line_comment_chars[] = "#";
  382.  
  383. main()
  384. {
  385.     int    ch;
  386.  
  387.     app_begin();
  388.     while((ch=do_scrub_next_char(stdin))!=EOF)
  389.         putc(ch,stdout);
  390. }
  391.  
  392. as_warn(str)
  393. char *str;
  394. {
  395.     fputs(str,stderr);
  396.     putc('\n',stderr);
  397. }
  398. #endif
  399.